const dayjs = require('dayjs');
/**
 * 性能监控工具
 * 用于监测和优化小程序性能
 */

// 性能标记类型
export const PERFORMANCE_MARK_TYPE = {
  PAGE_LOAD_START: 'page_load_start',
  PAGE_LOAD_END: 'page_load_end',
  DATA_FETCH_START: 'data_fetch_start',
  DATA_FETCH_END: 'data_fetch_end',
  RENDER_START: 'render_start',
  RENDER_END: 'render_end',
  CUSTOM: 'custom'
};

class PerformanceMonitor {
  constructor() {
    // 性能标记集合
    this._marks = {};
    
    // 性能测量集合
    this._measures = {};
    
    // 是否已启用性能监控
    this._enabled = false;
    
    // 性能日志记录
    this._logs = [];
    
    // 最大日志记录数量
    this._maxLogCount = 100;
    
    // 性能阈值配置，超过阈值会记录警告
    this._thresholds = {
      pageLoad: 2000, // 页面加载耗时阈值，单位ms
      dataFetch: 1000, // 数据获取耗时阈值，单位ms
      render: 500, // 渲染耗时阈值，单位ms
      jsExecution: 300, // JS执行耗时阈值，单位ms
      apiCall: 500 // API调用耗时阈值，单位ms
    };
  }
  
  /**
   * 启用性能监控
   * @param {Object} options 配置项
   */
  enable(options = {}) {
    this._enabled = true;
    
    // 更新配置
    if (options.maxLogCount) {
      this._maxLogCount = options.maxLogCount;
    }
    
    if (options.thresholds) {
      this._thresholds = { ...this._thresholds, ...options.thresholds };
    }
    
    console.info('[Performance] 性能监控已启用');
    return this;
  }
  
  /**
   * 禁用性能监控
   */
  disable() {
    this._enabled = false;
    console.info('[Performance] 性能监控已禁用');
    return this;
  }
  
  /**
   * 记录性能标记
   * @param {String} name 标记名称
   * @param {String} type 标记类型
   * @param {Object} data 额外数据
   */
  mark(name, type = PERFORMANCE_MARK_TYPE.CUSTOM, data = {}) {
    if (!this._enabled) return this;
    
    const timestamp = dayjs().valueOf();
    
    this._marks[name] = {
      name,
      type,
      timestamp,
      data
    };
    
    return this;
  }
  
  /**
   * 测量两个标记之间的性能
   * @param {String} name 测量名称
   * @param {String} startMarkName 开始标记名称
   * @param {String} endMarkName 结束标记名称
   * @param {Object} data 额外数据
   */
  measure(name, startMarkName, endMarkName, data = {}) {
    if (!this._enabled) return { duration: 0 };
    
    const startMark = this._marks[startMarkName];
    const endMark = this._marks[endMarkName];
    
    if (!startMark || !endMark) {
      console.warn(`[Performance] 无法完成测量，未找到标记: ${!startMark ? startMarkName : endMarkName}`);
      return { duration: 0 };
    }
    
    const duration = endMark.timestamp - startMark.timestamp;
    
    this._measures[name] = {
      name,
      startMarkName,
      endMarkName,
      startTime: startMark.timestamp,
      endTime: endMark.timestamp,
      duration,
      data: { ...startMark.data, ...endMark.data, ...data }
    };
    
    // 检查是否超过阈值
    this._checkThreshold(name, startMark.type, duration);
    
    // 记录性能日志
    this._addLog({
      type: 'measure',
      name,
      duration,
      startType: startMark.type,
      endType: endMark.type,
      timestamp: endMark.timestamp,
      data: { ...this._measures[name].data }
    });
    
    return this._measures[name];
  }
  
  /**
   * 检查性能测量是否超过阈值
   * @param {String} name 测量名称
   * @param {String} type 测量类型
   * @param {Number} duration 持续时间
   * @private
   */
  _checkThreshold(name, type, duration) {
    // 根据类型映射到对应的阈值
    let thresholdKey = 'custom';
    
    if (type === PERFORMANCE_MARK_TYPE.PAGE_LOAD_START) {
      thresholdKey = 'pageLoad';
    } else if (type === PERFORMANCE_MARK_TYPE.DATA_FETCH_START) {
      thresholdKey = 'dataFetch';
    } else if (type === PERFORMANCE_MARK_TYPE.RENDER_START) {
      thresholdKey = 'render';
    }
    
    const threshold = this._thresholds[thresholdKey];
    
    if (duration > threshold) {
      console.warn(`[Performance] 性能警告: ${name} 耗时 ${duration}ms，超过阈值 ${threshold}ms`);
      
      // 记录警告日志
      this._addLog({
        type: 'warning',
        name,
        duration,
        threshold,
        timestamp: dayjs().valueOf(),
        message: `性能警告: ${name} 耗时 ${duration}ms，超过阈值 ${threshold}ms`
      });
    }
  }
  
  /**
   * 添加性能日志
   * @param {Object} log 日志对象
   * @private
   */
  _addLog(log) {
    this._logs.push(log);
    
    // 如果超过最大数量，删除最早的记录
    if (this._logs.length > this._maxLogCount) {
      this._logs.shift();
    }
  }
  
  /**
   * 获取性能日志
   * @param {Number} limit 限制返回的日志数量
   * @returns {Array} 性能日志数组
   */
  getLogs(limit = this._maxLogCount) {
    return this._logs.slice(-limit);
  }
  
  /**
   * 获取警告日志
   * @returns {Array} 警告日志数组
   */
  getWarningLogs() {
    return this._logs.filter(log => log.type === 'warning');
  }
  
  /**
   * 获取指定测量结果
   * @param {String} name 测量名称
   * @returns {Object|null} 测量结果
   */
  getMeasure(name) {
    return this._measures[name] || null;
  }
  
  /**
   * 获取所有测量结果
   * @returns {Object} 所有测量结果
   */
  getAllMeasures() {
    return this._measures;
  }
  
  /**
   * 清除所有性能数据
   */
  clearAll() {
    this._marks = {};
    this._measures = {};
    this._logs = [];
    
    return this;
  }
  
  /**
   * 生成性能报告
   * @returns {Object} 性能报告
   */
  generateReport() {
    if (!this._enabled) {
      return { enabled: false };
    }
    
    const report = {
      enabled: true,
      timestamp: dayjs().valueOf(),
      summary: {
        totalMeasures: Object.keys(this._measures).length,
        totalWarnings: this.getWarningLogs().length,
        pageLoadTimes: [],
        dataFetchTimes: [],
        renderTimes: []
      },
      measures: this._measures,
      warnings: this.getWarningLogs()
    };
    
    // 收集各类型的性能数据
    Object.values(this._measures).forEach(measure => {
      const { startType, duration } = measure;
      
      if (startType === PERFORMANCE_MARK_TYPE.PAGE_LOAD_START) {
        report.summary.pageLoadTimes.push(duration);
      } else if (startType === PERFORMANCE_MARK_TYPE.DATA_FETCH_START) {
        report.summary.dataFetchTimes.push(duration);
      } else if (startType === PERFORMANCE_MARK_TYPE.RENDER_START) {
        report.summary.renderTimes.push(duration);
      }
    });
    
    // 计算平均值和最大值
    const calculateStats = (times) => {
      if (times.length === 0) return { avg: 0, max: 0, min: 0 };
      
      const sum = times.reduce((a, b) => a + b, 0);
      return {
        avg: Math.round(sum / times.length),
        max: Math.max(...times),
        min: Math.min(...times)
      };
    };
    
    report.summary.pageLoadStats = calculateStats(report.summary.pageLoadTimes);
    report.summary.dataFetchStats = calculateStats(report.summary.dataFetchTimes);
    report.summary.renderStats = calculateStats(report.summary.renderTimes);
    
    return report;
  }
  
  /**
   * 监测API调用性能
   * @param {Function} apiFn 要监测的API函数
   * @param {String} name API名称
   * @returns {Function} 包装后的函数
   */
  monitorApiCall(apiFn, name) {
    if (!this._enabled || typeof apiFn !== 'function') {
      return apiFn;
    }
    
    return async (...args) => {
      const markName = `api_${name}_${dayjs().valueOf()}`;
      this.mark(`${markName}_start`, 'api_call_start', { name, args });
      
      try {
        const result = await apiFn(...args);
        this.mark(`${markName}_end`, 'api_call_end', { name, result });
        this.measure(`API_${name}`, `${markName}_start`, `${markName}_end`, { name, args });
        return result;
      } catch (error) {
        this.mark(`${markName}_error`, 'api_call_error', { name, error });
        this.measure(`API_${name}_error`, `${markName}_start`, `${markName}_error`, { name, error });
        throw error;
      }
    };
  }
  
  /**
   * 监测页面生命周期性能
   * @param {Object} pageObject 页面对象
   * @param {String} pageName 页面名称
   * @returns {Object} 增强后的页面对象
   */
  monitorPage(pageObject, pageName) {
    if (!this._enabled) return pageObject;
    
    const enhancedPage = { ...pageObject };
    const monitor = this;
    
    // 增强onLoad
    const originalOnLoad = pageObject.onLoad;
    enhancedPage.onLoad = function(options) {
      const pageId = `${pageName}_${dayjs().valueOf()}`;
      this.__performancePageId = pageId;
      
      monitor.mark(`${pageId}_load_start`, PERFORMANCE_MARK_TYPE.PAGE_LOAD_START, {
        page: pageName,
        options
      });
      
      if (typeof originalOnLoad === 'function') {
        originalOnLoad.call(this, options);
      }
    };
    
    // 增强onReady
    const originalOnReady = pageObject.onReady;
    enhancedPage.onReady = function() {
      const pageId = this.__performancePageId;
      
      if (pageId) {
        monitor.mark(`${pageId}_load_end`, PERFORMANCE_MARK_TYPE.PAGE_LOAD_END, {
          page: pageName
        });
        
        monitor.measure(`PAGE_LOAD_${pageName}`, `${pageId}_load_start`, `${pageId}_load_end`, {
          page: pageName
        });
      }
      
      if (typeof originalOnReady === 'function') {
        originalOnReady.call(this);
      }
    };
    
    // 增强setData方法用于监控渲染性能
    const originalSetData = pageObject.setData;
    enhancedPage.setData = function(data, callback) {
      const pageId = this.__performancePageId;
      const setDataId = `setData_${dayjs().valueOf()}`;
      
      if (pageId && monitor._enabled) {
        monitor.mark(`${pageId}_${setDataId}_render_start`, PERFORMANCE_MARK_TYPE.RENDER_START, {
          page: pageName,
          dataKeys: Object.keys(data)
        });
        
        const wrappedCallback = () => {
          monitor.mark(`${pageId}_${setDataId}_render_end`, PERFORMANCE_MARK_TYPE.RENDER_END, {
            page: pageName
          });
          
          monitor.measure(`RENDER_${pageName}_${setDataId}`, 
            `${pageId}_${setDataId}_render_start`, 
            `${pageId}_${setDataId}_render_end`,
            { page: pageName }
          );
          
          if (typeof callback === 'function') {
            callback();
          }
        };
        
        return originalSetData.call(this, data, wrappedCallback);
      }
      
      return originalSetData.call(this, data, callback);
    };
    
    return enhancedPage;
  }
}

// 创建并导出单例
export const performanceMonitor = new PerformanceMonitor(); 